package com.devunion.bogdan.view.dialogs;

import com.devunion.bogdan.view.util.i18n;
import com.devunion.bogdan.view.util.DialogHelper;
import com.devunion.bogdan.view.util.ComponentFactory;
import com.devunion.bogdan.model.project.Ontology;
import com.devunion.bogdan.model.project.OntologyProperty;

import javax.swing.*;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.util.*;
import java.util.List;

import org.apache.commons.lang.StringUtils;

/**
 * @author Victar Liaskovich
 */
public class OntologyDialog extends JDialog {
    private Ontology ontology;
    private JTextArea jTextAreaText;
    private JTable jTableProperties;

    private OntologyPropertyDialog propertyDialog;
    private JButton jButtonRemove;
    private JButton jButtonEdit;

    public OntologyDialog(Frame owner) {
        super(owner, i18n.getString("OntologyDialog.Title"), true);

        initComponents();
        pack();
        setPreferredSize(new Dimension(420, 380));
    }

    private void initComponents() {
        getContentPane().setLayout(new GridBagLayout());

        jTextAreaText = new JTextArea(5, 10);

        final DefaultTableModel model = new DefaultTableModel(new Object[][]{}, new String[]{"Property", "Values"});

        jTableProperties = new JTable(model) {
            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }
        };

        JLabel jLabelProperty = new JLabel("Ontology Text:");
        jLabelProperty.setLabelFor(jTextAreaText);

        DialogHelper.placeComponent(getContentPane(), jLabelProperty,
                0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHEAST, GridBagConstraints.NONE,
                10, 10, 10, 0);

        if (ontology != null && ontology.getText() != null) {
            jTextAreaText.setText(ontology.getText());
        }

//        jTextAreaText.setBorder(BorderFactory.createEtchedBorder());
        DialogHelper.placeComponent(getContentPane(), new JScrollPane(jTextAreaText),
                1, 0, 1, 1, 1.0, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH,
                10, 0, 10, 0);

        JLabel jLabelValues = new JLabel("Ontology Properties:");
        jLabelValues.setLabelFor(jTableProperties);

        DialogHelper.placeComponent(getContentPane(), jLabelValues,
                0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHEAST, GridBagConstraints.NONE,
                10, 10, 10, 0);

        if (ontology != null && ontology.getOntologyProperties() != null) {
            initOntologyProperties(ontology.getOntologyProperties());
        }

        jTableProperties.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
        jTableProperties.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
            public void valueChanged(ListSelectionEvent e) {
                if (e.getValueIsAdjusting()) {
                    return;
                }

                updateOnSelection(e.getLastIndex());
            }
        });

        JScrollPane scrollPane = new JScrollPane(jTableProperties);
        jTableProperties.setFillsViewportHeight(true);

        DialogHelper.placeComponent(getContentPane(), scrollPane,
                1, 1, 1, 1, 1.0, 1, GridBagConstraints.NORTHEAST, GridBagConstraints.BOTH,
                10, 0, 10, 0);

        DialogHelper.placeComponent(getContentPane(), createButtonsPanel(model),
                1, 2, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
                10, 10, 10, 0);

//        DialogHelper.placeComponent(getContentPane(), ComponentFactory.getHR(),
//                0, 3, 2, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
//                10, 10, 10, 0);
//
        Component OkCancelPanel = ComponentFactory.createPanelButtonOkCancel(this, new ComponentFactory.ActionHandler() {
            public void execute() {
                if (ontology == null) {
                    ontology = new Ontology();

                    final TableModel model = jTableProperties.getModel();
                    for (int i = 0; i < model.getRowCount(); i++) {
                        OntologyProperty property = new OntologyProperty();
                        property.setName(model.getValueAt(i, 0).toString());
                        property.setValuesRepr(OntologyProperty.ValueSerializer.serialize(Arrays.asList(model.getValueAt(i, 1).toString().split(","))));

                        ontology.addOntologyPoperty(property);
                    }
                }

                ontology.setText(jTextAreaText.getText());

                setVisible(false);
            }
        }, new ComponentFactory.ActionHandler() {
            public void execute() {
                ontology = null;
                setVisible(false);
            }
        }, new ComponentFactory.ActionValidator() {
            public boolean validate() {
                return true;
            }
        });

        DialogHelper.placeComponent(getContentPane(), OkCancelPanel,
                0, 3, 2, 1, 1.0, 0.0, GridBagConstraints.NORTHEAST, GridBagConstraints.HORIZONTAL,
                20, 10, 10, 10);
    }

    private void updateOnSelection(int index) {
        if (index == -1) {
            return;
        }

        boolean enable = jTableProperties.getRowCount() != 0;

        jButtonEdit.setEnabled(enable);
        jButtonRemove.setEnabled(enable);
    }

    private JPanel createButtonsPanel(final DefaultTableModel model) {

        JPanel jPanelButtons = new JPanel(new FlowLayout(FlowLayout.CENTER));
        final JButton jButtonAdd = new JButton("Add");

        jButtonAdd.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (propertyDialog == null) {
                    propertyDialog = new OntologyPropertyDialog(DialogHelper.getMainFrame());
                }

                propertyDialog.setProperty("");
                propertyDialog.setValues("");

                propertyDialog.pack();
                propertyDialog.setLocationRelativeTo(null);
                propertyDialog.setVisible(true);

                final String property = propertyDialog.getProperty();
                final String values = propertyDialog.getValues();

                if (property == null || values == null) {
                    return;
                }

                model.addRow(new Object[]{property, values});

                // Update Ontology
                if (ontology == null) {
                    ontology = new Ontology();
                }

                final OntologyProperty p = new OntologyProperty();
                p.setName(property);
                p.setValuesRepr(OntologyProperty.ValueSerializer.serialize(Arrays.asList(StringUtils.split(values, ","))));

                ontology.addOntologyPoperty(p);
            }
        });
        jPanelButtons.add(jButtonAdd);

        jButtonRemove = new JButton("Remove");
        jButtonRemove.setEnabled(false);
        jButtonRemove.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                int row = jTableProperties.getSelectionModel().getLeadSelectionIndex();
                final String name = (String) model.getValueAt(row, 0);

                final int res = JOptionPane.showConfirmDialog(DialogHelper.getMainFrame(), "Are you sure to remove ontology property '" + name + "'?", "Remove property", JOptionPane.YES_NO_OPTION);

                if (res == JOptionPane.YES_OPTION) {
                    model.removeRow(row);
                }

                // Update Ontology
                if (ontology != null) {
                    final List<OntologyProperty> properties = ontology.getOntologyProperties();

                    OntologyProperty p = null;

                    for (int i = 0; i < properties.size(); i++) {
                        OntologyProperty property = properties.get(i);

                        if (property.getName().equals(name)) {
                            p = property;
                            break;
                        }
                    }

                    if (p != null) {
                        ontology.removeOntology(p);
                    }
                }
            }
        });
        jPanelButtons.add(jButtonRemove);

        jButtonEdit = new JButton("Edit");
        jButtonEdit.setEnabled(false);
        jButtonEdit.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (propertyDialog == null) {
                    propertyDialog = new OntologyPropertyDialog(DialogHelper.getMainFrame());
                }

                int row = jTableProperties.getSelectionModel().getLeadSelectionIndex();

                final String prop = (String) model.getValueAt(row, 0);
                propertyDialog.setProperty(prop);

                final String vals = (String) model.getValueAt(row, 1);
                propertyDialog.setValues(vals);

                propertyDialog.pack();
                propertyDialog.setLocationRelativeTo(null);
                propertyDialog.setVisible(true);

                final String property = propertyDialog.getProperty();
                final String values = propertyDialog.getValues();

                if ((property == null || values == null) || (prop.equals(property) && vals.equals(values))) {
                    return;
                }

                model.setValueAt(property, row, 0);
                model.setValueAt(values, row, 1);

                // Update Ontology
                if (ontology != null) {
                    final List<OntologyProperty> properties = ontology.getOntologyProperties();

                    OntologyProperty p = null;

                    for (int i = 0; i < properties.size(); i++) {
                        OntologyProperty pr = properties.get(i);

                        if (pr.getName().equals(prop)) {
                            p = pr;
                            break;
                        }
                    }

                    if (p != null) {
                        p.setName(property);
                        p.setValuesRepr(OntologyProperty.ValueSerializer.serialize(Arrays.asList(StringUtils.split(values, ","))));
                    }
                }
            }
        });
        jPanelButtons.add(jButtonEdit);

        return jPanelButtons;
    }

    private void clearTable(DefaultTableModel model) {

        while (model.getRowCount() > 0) {
            model.removeRow(0);
        }
    }

    private void clearTable() {
        clearTable((DefaultTableModel) jTableProperties.getModel());
    }

    private void initOntologyProperties(List<OntologyProperty> ontologyProperties) {
        final DefaultTableModel model = (DefaultTableModel) jTableProperties.getModel();

        clearTable(model);

        for (OntologyProperty p : ontologyProperties) {
            model.addRow(new Object[]{p.getName(), StringUtils.join(p.getValues().iterator(), ",")});
        }

        jTableProperties.setModel(model);
    }

    public Ontology getOntology() {
        return ontology;
    }

    public void setOntology(Ontology ontology) {
        this.ontology = ontology;

        if (ontology == null) {
            jTextAreaText.setText("");
            clearTable();
        } else {

            if (ontology.getText() != null) {
                jTextAreaText.setText(ontology.getText());
            }

            if (ontology.getOntologyProperties() != null) {
                initOntologyProperties(ontology.getOntologyProperties());
            }
        }
    }
}